#include <incctrls.h>
#include <inctypes.h>

/* ========================= open =========================== */

/*********************************************************************************
*
* krlsve_open_device - 调用设备驱动 分发程序 打开设备
*
* DESCRIPTION
*
*/

static sysstus_t krlsve_open_device
    (
    objnode_t * objndp
    )
    {

    /* 检验 objndp 的子域是否有效 */
    
    if (objndp->ptr == NULL)
        {
        return ERROR;
        }

    /* 调用设备驱动(分发)程序 */

    if (krl_dev_io (objndp) == ERROR)
        {
        return ERROR;
        }

    return OK;
    }

/*********************************************************************************
*
* krlsve_fs_open_core - 打开设备的核心函数
*
* DESCRIPTION
*
*/

static hand_t krlsve_fs_open_core
    (
    void *  file,
    uint_t  flag,
    uint_t  status
    )
    {
    devid_t     devid;
    device_t *  devp;
    objnode_t * objndp;
    thread_t *  thdp;
    hand_t      rethand;

    /* 获取调用该系统调用的应用程序进程描述符的指针 (即当前正在运行的进程) */

    thdp = krl_sched_return_curthd ();

    /* 检查flag中相关的位段 (文件类型) */

    if ((flag & KSVE_FILTP_MASK) == KSVE_FILTP_DEV)
        {
        goto open_dev_step; /* 执行打开设备步骤 */
        }
    else if ((flag & KSVE_FILTP_MASK) == KSVE_FILTP_FILE)
        {
        goto open_dev_file; /* 执行打开文件步骤 */
        }

    /* 检验失败 */

    return -1;

    /* 1.打开设备的步骤 */

open_dev_step:

    /* 获取设备主次设备号和设备序号 */

    devid.majtype = ((devid_t *) file)->majtype;
    devid.subtype = ((devid_t *) file)->subtype;
    devid.index   = ((devid_t *) file)->index;

    /* 根据设备ID新型查找设备 */

    devp = krl_find_device ((void *) &devid, DEV_ATTRFORM_IDN);

    if (devp == NULL)
        {
        return -1; /* 未找到指定的设备 */
        }

    /* 建立IO包 (objnode_t 结构) */

    objndp = krl_objnode_new ();

    if (objndp == NULL)
        {
        return -1; /* 建立IO包失败 */
        }

    /* 设置IO中的一些相关域 */

    objndp->opcode = IOIF_CODE_OPEN;     /* 设置IO包中的操作码为打开操作 */
    objndp->type   = OBJNODE_TYPE_DEV;   /* 设置打开类型为设备类型 */
    objndp->ptr    = devp;               /* 打开对象为查找到的设备 */

    /* 把IO包加入到响应进程的资源数组中, 并返回IO包指针的数组元素下标 */

    rethand = krl_thd_add_objnode (thdp, objndp);

    if (rethand == -1)
        {
        goto return_step; /* 加入失败 */
        }
    
    /* 调用设备驱动程序, 打开设备 */

    if (krlsve_open_device (objndp) == ERROR)
        {
        goto return_step; /* 打开失败 */
        }

    return rethand;

    /* 2.打开文件的步骤 */

open_dev_file:
    
    devid.majtype = DEVICE_CLASSITY_FILESYS; /* 类型为文件系统 */
    devid.subtype = 0;
    devid.index   = 0;

    /* 根据 devid_t 结构中的信息查找设备 */

    devp = krl_find_device ((void *) &devid, DEV_ATTRFORM_IDN);

    if (devp == NULL)
        {
        return -1; /* 没找到文件系统设备 */
        }

    /* 建立IO包 (objnode_t结构) */

    objndp = krl_objnode_new ();

    if (objndp == NULL)
        {
        return -1; /* 建立IO包失败 */
        }

    /* 设置IO中的一些相关域 */

    objndp->opcode = IOIF_CODE_OPEN;     /* 设置IO包中的操作码为打开操作 */
    objndp->type   = OBJNODE_TYPE_FIL;   /* 设置打开类型为文件类型 */
    objndp->ptr    = devp;               /* 打开对象为查找到的设备 */
    objndp->fname  = file;               /* 指定文件名 */

    /* 检查 flag 的位段, 判断是否为新建文件操作 */

    if (((flag >> KSVE_FILPER_BITS) & KSVE_FILPER_MASK) == KSVE_FILPER_NEW)
        {
        objndp->acsflag = FSDEV_OPFLG_NEWFILE; /* 设置文件访问标志为 创建新文件 */

        /* 调用设备驱动程序, 打开设备 */
    
        if (krlsve_open_device (objndp) == ERROR)
            {
            goto return_step;
            }

        /* 创建文件成功, 删除 IO 包 */

        if (krl_objnode_delete (objndp) == FALSE)
            {
            krl_system_die ("krlsve_open_core err1\r\n");
            return -1;
            }
        
        /* 创建文件成功返回 0 */

        return 0;
        }
    else
        {
        objndp->acsflag = FSDEV_OPFLG_OPNFILE; /* 设置文件访问标志为 打开文件 */

        /* 把IO包加入到相应进程的资源数组中, 并返回IO包指针的数组元素下标 */
    
        rethand = krl_thd_add_objnode (thdp, objndp);
    
        if (rethand == -1)
            {
            goto return_step;
            }
        
        /* 调用打开设备驱动程序 */
    
        if (krlsve_open_device (objndp) == ERROR)
            {
            goto return_step;
            }
    
        return rethand;
        }

    /* 错误处理相关代码 */

return_step:

    /* IO包加入到相应进程的资源数组成功, 打开文件失败, 删除IO */

    if (rethand != -1)
        {
        if (krl_thd_delete_objnode (thdp, rethand) == -1)
            {
            krl_system_die ("krlsve_open_core err2\r\n");
            return -1;
            }
        }

    /* 删除 IO 包 */

    if (krl_objnode_delete (objndp) == FALSE)
        {
        krl_system_die ("krlsve_open_core err3\r\n");
        return -1;
        }

    return -1;
    }

/*********************************************************************************
*
* krlsve_fs_open - 打开设备函数
*
* DESCRIPTION
*
*/

hand_t krlsve_fs_open
    (
    void *  file,
    uint_t  flag,
    uint_t  status
    )
    {
    hand_t rethand;

    /* 检验文件有效性 */

    if (file == NULL)
        {
        return ERROR;
        }

    /* 打开设备核心函数 */

    rethand = krlsve_fs_open_core (file, flag, status);

    return rethand;
    }
    

/* ========================= close =========================== */

/*********************************************************************************
*
* krlsve_close_device - 调用设备驱动 分发程序 关闭设备
*
* DESCRIPTION
*
*/

static sysstus_t krlsve_close_device
    (
    objnode_t * objndp
    )
    {

    /* 检验 objndp 的子域是否有效 */
    
    if (objndp->ptr == NULL)
        {
        return ERROR;
        }

    /* 调用设备驱动(分发)程序 */

    if (krl_dev_io (objndp) == ERROR)
        {
        return ERROR;
        }

    return OK;
    }

/*********************************************************************************
*
* krlsve_fs_close_core - 关闭设备的核心函数
*
* DESCRIPTION
*
*/

static sysstus_t krlsve_fs_close_core
    (
    hand_t hand
    )
    {
    objnode_t * objndp;
    thread_t *  thdp;

    /* 获取调用该系统调用的应用程序进程描述符的指针 (即当前正在运行的进程) */

    thdp = krl_sched_return_curthd ();

    /* 根据 hand 参数, 获取相应进程资源数组中的特定IO包 */

    objndp = krl_thd_return_objnode (thdp, hand);

    if (objndp == NULL)
        {
        return ERROR; /* 获取IO包失败 */
        }

    /* 如果IO包打开类型是文件类型或者设备类型, 就设置IO包中的操作码为关闭操作 */

    if ((objndp->type == OBJNODE_TYPE_DEV) || 
        (objndp->type == OBJNODE_TYPE_FIL))
        {
        objndp->opcode = IOIF_CODE_CLOSE; /* 设置IO包的操作码为关闭操作 */
        goto close_dev_step;
        }

    /* IO类型非法, 返回失败 */

    return ERROR;

close_dev_step:

    /* 调用关闭设备驱驱动程序 */

    if (krlsve_close_device (objndp) == ERROR)
        {
        return ERROR; /* 调用关闭设备驱动失败 */
        }

    /* 释放进程资源数组中的 IO 包 */

    if (krl_thd_delete_objnode (thdp, hand) == -1)
        {
        krl_system_die ("krlsve_fs_close_core err1\r\n");
        return ERROR;
        }

    /* 删除 IO 包 */

    if (krl_objnode_delete (objndp) == FALSE)
        {
        krl_system_die ("krlsve_fs_close_core err2\r\n");
        return ERROR;
        }

    /* 关闭文件/设备成功 */

    return OK;
    }

/*********************************************************************************
*
* krlsve_fs_close - 关闭设备函数
*
* DESCRIPTION
*
*/

sysstus_t krlsve_fs_close
    (
    hand_t hand
    )
    {
    sysstus_t retstus;

    /* 检验hand值有效性 */

    if ((hand <= THD_SRC_NUL_NBR) || (hand >= THD_SRC_MAX_NBR))
        {
        return ERROR;
        }

    /* 关闭设备核心函数 */

    retstus = krlsve_fs_close_core (hand);

    return retstus;
    }

/* ========================= read =========================== */

/*********************************************************************************
*
* krlsve_read_device - 调用设备驱动 分发程序 读取设备
*
* DESCRIPTION
*
*/

static sysstus_t krlsve_read_device
    (
    objnode_t * objndp
    )
    {

    /* 检验 objndp 的子域是否有效 */
    
    if (objndp->ptr == NULL)
        {
        return ERROR;
        }

    /* 调用设备驱动(分发)程序 */

    if (krl_dev_io (objndp) == ERROR)
        {
        return ERROR;
        }

    return OK;
    }

/*********************************************************************************
*
* krlsve_fs_read_core - 读取设备的核心函数
*
* DESCRIPTION
*
*/

static sysstus_t krlsve_fs_read_core
    (
    hand_t hand,
    buf_t  buf,
    size_t len,
    uint_t flag
    )
    {
    objnode_t * objndp;
    thread_t *  thdp;
    sysstus_t   retstus;

    /* 获取调用该系统调用的应用程序进程描述符的指针 (即当前正在运行的进程) */

    thdp = krl_sched_return_curthd ();

    /* 根据 hand 参数, 获取相应进程资源数组中的特定IO包 */

    objndp = krl_thd_return_objnode (thdp, hand);

    if (objndp == NULL)
        {
        return ERROR; /* 获取IO包失败 */
        }

    /* 如果IO包打开类型是文件类型或者设备类型, 就设置IO包中的操作码为关闭操作 */

    if ((objndp->type == OBJNODE_TYPE_DEV) || 
        (objndp->type == OBJNODE_TYPE_FIL))
        {

        /* 设置IO中的一些相关域 */

        objndp->opcode  = IOIF_CODE_READ; /* 设置IO包的操作码为读操作 */
        objndp->buf     = buf;            /* 设置存放数据的缓冲区 */
        objndp->bufsz   = FSLOGBLK_SZ;    /* 缓冲区的大小 */
        objndp->len     = len;            /* 设置读取数据的长度 */
        objndp->acsflag = flag;           /* 设置访问标志 */

        /* 调用读取设备数据的函数接口 */

        retstus = krlsve_read_device (objndp);

        return retstus;
        }

    /* IO类型非法, 返回失败 */

    return ERROR;
    }

/*********************************************************************************
*
* krlsve_fs_read - 读取设备函数
*
* DESCRIPTION
*
*/

sysstus_t krlsve_fs_read
    (
    hand_t hand,
    buf_t  buf,
    size_t len,
    uint_t flag
    )
    {
    sysstus_t retstus;

    /* 检验hand值有效性 */

    if (((hand <= THD_SRC_NUL_NBR) || (hand >= THD_SRC_MAX_NBR)) ||
        (buf == NULL) || (len < 1))
        {
        return ERROR;
        }

    /* 读设备核心函数 */

    retstus = krlsve_fs_read_core (hand, buf, len, flag);

    return retstus;
    }

/* ========================= write =========================== */

/*********************************************************************************
*
* krlsve_write_device - 调用设备驱动 分发程序 写设备
*
* DESCRIPTION
*
*/

static sysstus_t krlsve_write_device
    (
    objnode_t * objndp
    )
    {

    /* 检验 objndp 的子域是否有效 */
    
    if (objndp->ptr == NULL)
        {
        return ERROR;
        }

    /* 调用设备驱动(分发)程序 */

    if (krl_dev_io (objndp) == ERROR)
        {
        return ERROR;
        }

    return OK;
    }

/*********************************************************************************
*
* krlsve_fs_write_core - 写设备的核心函数
*
* DESCRIPTION
*
*/

static sysstus_t krlsve_fs_write_core
    (
    hand_t hand,
    buf_t  buf,
    size_t len,
    uint_t flag
    )
    {
    objnode_t * objndp;
    thread_t *  thdp;
    sysstus_t   retstus;

    /* 获取调用该系统调用的应用程序进程描述符的指针 (即当前正在运行的进程) */

    thdp = krl_sched_return_curthd ();

    /* 根据 hand 参数, 获取相应进程资源数组中的特定IO包 */

    objndp = krl_thd_return_objnode (thdp, hand);

    if (objndp == NULL)
        {
        return ERROR; /* 获取IO包失败 */
        }

    /* 如果IO包打开类型是文件类型或者设备类型, 就设置IO包中的操作码为关闭操作 */

    if ((objndp->type == OBJNODE_TYPE_DEV) || 
        (objndp->type == OBJNODE_TYPE_FIL))
        {

        /* 设置IO中的一些相关域 */

        objndp->opcode  = IOIF_CODE_WRITE; /* 设置IO包的操作码为写操作 */
        objndp->buf     = buf;             /* 设置存放数据的缓冲区 */
        objndp->bufsz   = FSLOGBLK_SZ;     /* 缓冲区的大小 */
        objndp->len     = len;             /* 设置读取数据的长度 */
        objndp->acsflag = flag;            /* 设置访问标志 */

        /* 调用写设备数据的函数接口 */

        retstus = krlsve_write_device (objndp);

        return retstus;
        }

    /* IO类型非法, 返回失败 */

    return ERROR;
    }

/*********************************************************************************
*
* krlsve_fs_write - 写设备函数
*
* DESCRIPTION
*
*/

sysstus_t krlsve_fs_write
    (
    hand_t hand,
    buf_t  buf,
    size_t len,
    uint_t flag
    )
    {
    sysstus_t retstus;

    /* 检验hand值有效性 */

    if (((hand <= THD_SRC_NUL_NBR) || (hand >= THD_SRC_MAX_NBR)) ||
        (buf == NULL) || (len == 0))
        {
        return ERROR;
        }

    /* 写设备核心函数 */

    retstus = krlsve_fs_write_core (hand, buf, len, flag);

    return retstus;
    }

/* ========================= ioctl =========================== */

/*********************************************************************************
*
* krlsve_ioctl_device - 调用设备驱动 分发程序 IOCTL
*
* DESCRIPTION
*
*/

static sysstus_t krlsve_ioctl_device
    (
    objnode_t * objndp
    )
    {

    /* 检验 objndp 的子域是否有效 */
    
    if (objndp->ptr == NULL)
        {
        return ERROR;
        }

    /* 调用设备驱动(分发)程序 */

    if (krl_dev_io (objndp) == ERROR)
        {
        return ERROR;
        }

    return OK;
    }

/*********************************************************************************
*
* krlsve_fs_ioctl_core - IOCTL设备的核心函数
*
* DESCRIPTION
*
*/

static sysstus_t krlsve_fs_ioctl_core
    (
    hand_t hand,
    buf_t  buf,
    uint_t ioctlcmd,
    uint_t flag
    )
    {
    objnode_t * objndp;
    thread_t *  thdp;
    sysstus_t   retstus;

    /* 获取调用该系统调用的应用程序进程描述符的指针 (即当前正在运行的进程) */

    thdp = krl_sched_return_curthd ();

    /* 根据 hand 参数, 获取相应进程资源数组中的特定IO包 */

    objndp = krl_thd_return_objnode (thdp, hand);

    if (objndp == NULL)
        {
        return ERROR; /* 获取IO包失败 */
        }

    /* 如果IO包打开类型是文件类型或者设备类型, 就设置IO包中的操作码为关闭操作 */

    if ((objndp->type == OBJNODE_TYPE_DEV) || 
        (objndp->type == OBJNODE_TYPE_FIL))
        {

        /* 设置IO中的一些相关域 */

        objndp->opcode   = IOIF_CODE_IOCTL; /* 设置IO包的操作码为IOCTL操作 */
        objndp->buf      = buf;             /* 设置存放数据的缓冲区 */
        objndp->ioctlcmd = ioctlcmd;        /* 设置IOCTL控制码 */
        objndp->acsflag  = flag;            /* 设置访问标志 */

        /* 调用IOCTL设备数据的函数接口 */

        retstus = krlsve_ioctl_device (objndp);

        return retstus;
        }

    /* IO类型非法, 返回失败 */

    return ERROR;
    }

/*********************************************************************************
*
* krlsve_fs_ioctl - IOCTL设备函数
*
* DESCRIPTION
*
*/

sysstus_t krlsve_fs_ioctl
    (
    hand_t hand,
    buf_t  buf,
    uint_t ioctlcmd,
    uint_t flag
    )
    {
    sysstus_t retstus;

    /* 检验hand值有效性 */

    if ((hand <= THD_SRC_NUL_NBR) || (hand >= THD_SRC_MAX_NBR))
        {
        return ERROR;
        }

    /* IOCTL设备核心函数 */

    retstus = krlsve_fs_ioctl_core (hand, buf, ioctlcmd, flag);

    return retstus;
    }

/* ========================= lseek =========================== */

/*********************************************************************************
*
* krlsve_lseek_device - 调用设备驱动 分发程序 lseek
*
* DESCRIPTION
*
*/

static sysstus_t krlsve_lseek_device
    (
    objnode_t * objndp
    )
    {

    /* 检验 objndp 的子域是否有效 */
    
    if (objndp->ptr == NULL)
        {
        return ERROR;
        }

    /* 调用设备驱动(分发)程序 */

    if (krl_dev_io (objndp) == ERROR)
        {
        return ERROR;
        }

    return OK;
    }

/*********************************************************************************
*
* krlsve_fs_lseek_core - lseek设备的核心函数
*
* DESCRIPTION
*
*/

static sysstus_t krlsve_fs_lseek_core
    (
    hand_t hand,
    uint_t lofset,
    uint_t flag
    )
    {
    objnode_t * objndp;
    thread_t *  thdp;
    sysstus_t   retstus;

    /* 获取调用该系统调用的应用程序进程描述符的指针 (即当前正在运行的进程) */

    thdp = krl_sched_return_curthd ();

    /* 根据 hand 参数, 获取相应进程资源数组中的特定IO包 */

    objndp = krl_thd_return_objnode (thdp, hand);

    if (objndp == NULL)
        {
        return ERROR; /* 获取IO包失败 */
        }

    /* 如果IO包打开类型是文件类型或者设备类型, 就设置IO包中的操作码为关闭操作 */

    if ((objndp->type == OBJNODE_TYPE_DEV) || 
        (objndp->type == OBJNODE_TYPE_FIL))
        {

        /* 设置IO中的一些相关域 */

        objndp->opcode   = IOIF_CODE_LSEEK; /* 设置IO包的操作码为LSEEK操作 */
        objndp->acsflag  = flag;            /* 设置访问标志 */

        /* 调用lseek设备数据的函数接口 */

        retstus = krlsve_lseek_device (objndp);

        return retstus;
        }

    /* IO类型非法, 返回失败 */

    return ERROR;
    }

/*********************************************************************************
*
* krlsve_fs_lseek - lseek设备函数
*
* DESCRIPTION
*
*/

sysstus_t krlsve_fs_lseek
    (
    hand_t hand,
    uint_t lofset,
    uint_t flag
    )
    {
    sysstus_t retstus;

    /* 检验hand值有效性 */

    if ((hand <= THD_SRC_NUL_NBR) || (hand >= THD_SRC_MAX_NBR))
        {
        return ERROR;
        }

    /* IOCTL设备核心函数 */

    retstus = krlsve_fs_lseek_core (hand, lofset, flag);

    return retstus;
    }